using System;
using System.Linq.Expressions;

namespace BulkUploadGovernanceFiles.MongoSpecification
{
    public abstract class CompositeSpecification<T> : ISpecification<T>
    {
        private Func<T, bool> _compiledExpression;

        private Func<T, bool> CompiledExpression
        {
            get { return _compiledExpression ?? (_compiledExpression = SpecExpression.Compile()); }
        }

        public abstract Expression<Func<T, bool>> SpecExpression { get; }

        public ISpecification<T> And(ISpecification<T> other)
        {
            return new AndSpecification<T>(this, other);
        }

        public ISpecification<T> Or(ISpecification<T> other)
        {
            return new OrSpecification<T>(this, other);
        }

        public ISpecification<T> Not(ISpecification<T> other)
        {
            return new NotSpecification<T>(other);
        }

        public bool IsSatisfiedBy(T candidate)
        {
            return CompiledExpression(candidate);
        }
    }
}